/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbLib-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_01			*/
/*	File:		GlbMap.h			*/
/********************************************************/

#ifndef _GLBMAP_H
#define	_GLBMAP_H

#include "GlbGlobal.h"

#include <iostream>
#include <string>
#include <map>

namespace GlbCls
{

typedef struct tagGlbMapDigit
{
	bool operator()(const ULONG ulKey1, const ULONG ulKey2) const {
		return static_cast<long>(ulKey1 - ulKey2) < 0;
	}
}GLBMAPDIGIT_O;

typedef struct tagGlbMapString
{
	bool operator()(const std::string CKey1, const std::string CKey2) const {
		return CKey1 < CKey2;
	}
}GLBMAGLBTRING_O;

template<typename K, typename V, typename C>
class CGlbMap
{
public:
	typedef typename std::map<K, V, C>		GLB_MAP;
	typedef typename std::map<K, V, C>::iterator	GLB_ITE;

	CGlbMap() {};
	virtual ~CGlbMap() {};

	void GlbMapClear();
	bool GlbMapEmpty();
	ULONG GlbMapSize();
	GLB_ITE GlbMapEnd();
	GLB_ITE GlbMapBegin();
	void GlbMapDestroy();
	void GlbMapDisplay();
	void GlbMapTraversal(int (*pFunction)(void*));

	inline V* GlbMapSelect(K);
	inline void GlbMapDelete(K);
	inline bool GlbMapInsert(K, V&);
	inline bool GlbMapUpdate(K, V&);
	inline bool GlbMapSelect(K, V&, int);

protected:
	GLB_MAP m_GLBap;

private:

};

template<typename K, typename V, typename C>
void CGlbMap<K, V, C>::GlbMapClear()
{
	m_GLBap.clear();

	return;
}

template<typename K, typename V, typename C>
bool CGlbMap<K, V, C>::GlbMapEmpty()
{
	return m_GLBap.empty();
}

template<typename K, typename V, typename C>
ULONG CGlbMap<K, V, C>::GlbMapSize()
{
	return (ULONG)m_GLBap.size();
}

template<typename K, typename V, typename C>
typename std::map<K, V, C>::iterator CGlbMap<K, V, C>::GlbMapEnd()
{
	return m_GLBap.end();
}

template<typename K, typename V, typename C>
typename std::map<K, V, C>::iterator CGlbMap<K, V, C>::GlbMapBegin()
{
	return m_GLBap.begin();
}

template<typename K, typename V, typename C>
void CGlbMap<K, V, C>::GlbMapDestroy()
{
	GLB_ITE iteCur = GlbMapBegin();

	for (; iteCur != GlbMapEnd(); iteCur ++) {
		free(iteCur->second);
	}

	m_GLBap.clear();

	return;
}

template<typename K, typename V, typename C>
void CGlbMap<K, V, C>::GlbMapDisplay()
{
	int iCount = 0;
	GLB_ITE iteCur = GlbMapBegin();

	for (; iteCur != GlbMapEnd(); iteCur ++) {
		GLB_PRINT("%04d: ", iCount ++);
		std::cout << "{ " << iteCur->first << ":\t" << iteCur->second << " }" << std::endl;
	}

	return;
}

template<typename K, typename V, typename C>
void CGlbMap<K, V, C>::GlbMapTraversal(int (*pFunction)(void*))
{
	GLB_ITE iteCur = GlbMapBegin();

	for (; iteCur != GlbMapEnd(); iteCur ++) {
		(*pFunction)((void*)&iteCur->second);
	}

	return;
}

template<typename K, typename V, typename C>
inline void CGlbMap<K, V, C>::GlbMapDelete(K Key)
{
	m_GLBap.erase(Key);

	return;
}

template<typename K, typename V, typename C>
inline bool CGlbMap<K, V, C>::GlbMapInsert(K Key, V& Value)
{
	std::pair<GLB_ITE, bool> pairReturn;
	std::pair<K, V> pairInsert(Key, Value);

	pairReturn = m_GLBap.insert(pairInsert);

	return pairReturn.second;
}

template<typename K, typename V, typename C>
inline bool CGlbMap<K, V, C>::GlbMapUpdate(K Key, V& Value)
{
	GlbMapDelete(Key);

	return GlbMapInsert(Key, Value);
}

template<typename K, typename V, typename C>
inline bool CGlbMap<K, V, C>::GlbMapSelect(K Key, V& Value, int iSize)
{
	GLB_ITE iteCur = m_GLBap.find(Key);

	if (iteCur != GlbMapEnd()) {
		memcpy(static_cast<void*>(&Value), (void*)&iteCur->second, iSize);
	}
	else {
		return false;
	}

	return true;
}

template<typename K, typename V, typename C>
inline V* CGlbMap<K, V, C>::GlbMapSelect(K Key)
{
	V* pReturn = NULL;
	GLB_ITE iteCur = m_GLBap.find(Key);

	if (iteCur != GlbMapEnd()) {
		pReturn = (V*)iteCur->second;
	}

	return pReturn;
}

} /* GlbCls */

#endif /* _GLBMAP_H */
